using System;
using System.Collections.Generic;
using System.Reflection;

namespace SiliverlightJavascriptIntelli
{
    public static class SilverlightTypeCollctor
    {
        public static List<SilverlightType> GetTypesToGenerateJavascriptFor()
        {
            List<SilverlightType> ReturnValues = new List<SilverlightType>();

            IterateOverAllTypesInAgclrAndConvertToSilverlightType(ReturnValues);

            return ReturnValues;
        }

        public static void IterateOverAllTypesInAgclrAndConvertToSilverlightType(List<SilverlightType> ReturnValues)
        {
            foreach (Type curCLRTypeToExtractTypeDataFrom in TypeHelper.agClrAssembly.GetTypes())
            {
                if (curCLRTypeToExtractTypeDataFrom.IsPublic)
                    ReturnValues.Add(ConvertCLRTypeToSilverlightType(curCLRTypeToExtractTypeDataFrom));
            }
        }

        public static SilverlightType ConvertCLRTypeToSilverlightType(Type curCLRTypeToExtractTypeDataFrom)
        {
            SilverlightType newSilverlightType = new SilverlightType();

            newSilverlightType.Name = TypeHelper.ConvertTypeToString(curCLRTypeToExtractTypeDataFrom);
            newSilverlightType.SetTypeHierhcy(curCLRTypeToExtractTypeDataFrom);
            newSilverlightType.CanBePrimitiveType = !TypeHelper.IsFromDependencyObject(curCLRTypeToExtractTypeDataFrom);
            newSilverlightType.BaseTypeName = TypeHelper.ConvertTypeToString(curCLRTypeToExtractTypeDataFrom.BaseType);

            IterateAndAddStaticFields(curCLRTypeToExtractTypeDataFrom, newSilverlightType);
            
            IterateAndAddProperties(curCLRTypeToExtractTypeDataFrom, newSilverlightType);

            IterateAndAddMethods(curCLRTypeToExtractTypeDataFrom, newSilverlightType);

            IterateAndAddEvents(curCLRTypeToExtractTypeDataFrom, newSilverlightType);

            return newSilverlightType;
        }

        private static void IterateAndAddStaticFields(Type curCLRTypeToExtractTypeDataFrom, SilverlightType newSilverlightType)
        {
            foreach (FieldInfo curFieldInfoToConvert in curCLRTypeToExtractTypeDataFrom.GetFields(BindingFlags.Static | BindingFlags.Public))
            {
                if (TypeHelper.IsFromDependencyProperty(curFieldInfoToConvert.FieldType)
                    || TypeHelper.IsEnum(curFieldInfoToConvert.FieldType))
                    newSilverlightType.StaticFields.Add(SilverlightStaticField.ConvertFieldInfoToSilverlightStaticDependencyProperty(curFieldInfoToConvert, newSilverlightType));
            }
        }

        private static void IterateAndAddEvents(Type curCLRTypeToExtractTypeDataFrom, SilverlightType newSilverlightType)
        {
            foreach (EventInfo curEventInfoToConvert in curCLRTypeToExtractTypeDataFrom.GetEvents())
            {
                newSilverlightType.Events.Add(SilverlightEvent.ConvertEventInfoToSilverlightEvent(curEventInfoToConvert, newSilverlightType));
            }
        }

        public static void IterateAndAddMethods(Type curCLRTypeToExtractTypeDataFrom, SilverlightType newSilverlightType)
        {
            foreach (MethodInfo curMethodInfoToConvert in curCLRTypeToExtractTypeDataFrom.GetMethods())
            {

                if (!curMethodInfoToConvert.IsSpecialName)
                newSilverlightType.Methods.Add(SilverlightMethod.ConvertMethodInfoToSilverlightMethod(curMethodInfoToConvert, newSilverlightType));
            }
        }

        public static void IterateAndAddProperties(Type curCLRTypeToExtractTypeDataFrom, SilverlightType newSilverlightType)
        {
            foreach (PropertyInfo curPropertyInfoToConvert in curCLRTypeToExtractTypeDataFrom.GetProperties())
            {
                newSilverlightType.Properties.Add(SilverlightProperty.ConvertPropertyInfoToSilverlightProperty(curPropertyInfoToConvert, newSilverlightType));
            }
        }
    }
}